package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vo.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import org.apache.commons.beanutils.BeanUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;


public class HotArticleServiceImple implements HotArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;
    /**
     * 热点文章定时计算
     */
    @Override
    public void computeHotArticle() {
        //1.获取前五天的文章数据
        Date dateParam = DateTime.now().minusDays(5).toDate();
        List<ApArticle> articleByLast5days = apArticleMapper.findArticleByLast5days(dateParam);

        //2.对文章进行算分
        List<HotArticleVo> hotArticleVoList = computeHotArticleScore(articleByLast5days);

        //3.为每个频道缓存30条热点数据
        cacheTagToRedis(hotArticleVoList);
    }


    @Autowired
    private IWemediaClient iWemediaClient;

    @Autowired
    private CacheService cacheService;

    /**
     * 为每个频道缓存30条热点数据
     * @param hotArticleVoList
     */
    private void cacheTagToRedis(List<HotArticleVo> hotArticleVoList) {
        // 获取集合数据
        ResponseResult channles = iWemediaClient.getChannles();
        if(channles != null){
            String jsonString = JSON.toJSONString(channles);
            List<WmChannel> channels = JSON.parseArray(jsonString, WmChannel.class);

            for (WmChannel channel : channels) {
                // 分频道
                List<HotArticleVo> hotArticleVos = hotArticleVoList.stream().filter(x -> x.getChannelId().equals(channel.getId())).collect(Collectors.toList());

                // 按照分值排序
                hotArticleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());

                // 判断是否30条
                if(hotArticleVos.size() > 30){
                    hotArticleVos.subList(0,30);
                }
                // 以 频道id 作为键    以该频道下的所有文章数据作为值  存入Redis
                cacheService.set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE+channel.getId(),JSON.toJSONString(hotArticleVos));
            }
        }

        // 设置推荐数据
        // 按照分值排序
        hotArticleVoList = hotArticleVoList.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());

        // 判断是否30条
        if(hotArticleVoList.size() > 30){
            hotArticleVoList.subList(0,30);
        }
        // 以 频道id 作为键    以该频道下的所有文章数据作为值  存入Redis
        cacheService.set(ArticleConstants.DEFAULT_TAG,JSON.toJSONString(hotArticleVoList));
    }

    /**
     * 算分并返回热点文章试图集合
     * @param articleByLast5days
     * @return
     */
    private List<HotArticleVo> computeHotArticleScore(List<ApArticle> articleByLast5days) {
        List<HotArticleVo> hotArticleVoList = new ArrayList<>();

        try {
        for (ApArticle articleByLast5day : articleByLast5days) {
            HotArticleVo hotArticleVo = new HotArticleVo();
            BeanUtils.copyProperties(articleByLast5day,hotArticleVo);
            Integer score = computeScore(articleByLast5day);
            hotArticleVo.setScore(score);
            hotArticleVoList.add(hotArticleVo);
            }
        }catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return hotArticleVoList;
    }

    /**
     * 根据各个权重来计算分值
     * @param articleByLast5day
     * @return
     */
    private Integer computeScore(ApArticle articleByLast5day) {
        Integer score = 0;

        if(articleByLast5day != null){
            if(articleByLast5day.getLikes() >= 0){
                score += articleByLast5day.getLikes()* ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
            }
            if(articleByLast5day.getViews() >= 0){
                score += articleByLast5day.getViews();
            }
            if(articleByLast5day.getComment() >= 0){
                score += articleByLast5day.getComment()* ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
            }
            if(articleByLast5day.getCollection() >= 0){
                score += articleByLast5day.getCollection()* ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
            }

        }

        return score;

    }
}
